x11: Implement INCR reads
authorBenjamin Otte <otte@redhat.com>
Sun, 19 Nov 2017 19:52:36 +0000 (20:52 +0100)
committerBenjamin Otte <otte@redhat.com>
Sun, 3 Dec 2017 04:43:24 +0000 (05:43 +0100)
gdk/x11/gdkselectioninputstream-x11.c

index e4704ab78d25fbf0b1e31401e5737f988dc3cb87..97ceedd5287799fdb07e7fab1ab81ce1a6c8982d 100644 (file)
@@ -46,6 +46,7 @@ struct GdkX11SelectionInputStreamPrivate {
   gsize pending_size;
 
   guint complete : 1;
+  guint incr : 1;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GdkX11SelectionInputStream, gdk_x11_selection_input_stream, G_TYPE_INPUT_STREAM);
@@ -340,33 +341,50 @@ gdk_x11_selection_input_stream_filter_event (GdkXEvent *xev,
   XEvent *xevent = xev;
   Display *xdisplay;
   Window xwindow;
-
-#if 0
-  GList *tmp_list;
-  GtkRetrievalInfo *info = NULL;
-  GdkWindow *window;
   GBytes *bytes;
-  gint length;
-  GdkAtom type;
-  GdkAtom selection;
-  GdkAtom property;
-  gint   format;
-  guint32 time;
-#endif
+  Atom type;
+  gint format;
 
   xdisplay = gdk_x11_display_get_xdisplay (priv->display);
   xwindow = GDK_X11_DISPLAY (priv->display)->leader_window;
 
-  if (xevent->xany.window != xwindow)
+  if (xevent->xany.display != xdisplay ||
+      xevent->xany.window != xwindow)
     return GDK_FILTER_CONTINUE;
 
   switch (xevent->type)
     {
+      case PropertyNotify:
+        if (!priv->incr ||
+            xevent->xproperty.atom != priv->xproperty ||
+            xevent->xproperty.state != PropertyNewValue)
+          return GDK_FILTER_CONTINUE;
+
+      GDK_NOTE(SELECTION, g_printerr ("%s:%s: got PropertyNotify durin INCR\n", priv->selection, priv->target));
+      
+      bytes = get_selection_property (xdisplay, xwindow, xevent->xproperty.atom, &type, &format);
+      if (bytes == NULL)
+        { 
+          /* error, should we signal one? */
+          gdk_x11_selection_input_stream_complete (stream);
+        }
+      else if (g_bytes_get_size (bytes) == 0 || type == None)
+        {
+          g_bytes_unref (bytes);
+          gdk_x11_selection_input_stream_complete (stream);
+        }
+      else
+        {
+          g_queue_push_tail (&priv->chunks, bytes);
+          gdk_x11_selection_input_stream_flush (stream);
+        }
+
+      XDeleteProperty (xdisplay, xwindow, xevent->xproperty.atom);
+
+      return GDK_FILTER_CONTINUE;
+
     case SelectionNotify:
       {
-        GBytes *bytes;
-        Atom type;
-        gint format;
 
         if (priv->xselection != xevent->xselection.selection ||
             priv->xtarget != xevent->xselection.target)
@@ -385,17 +403,18 @@ gdk_x11_selection_input_stream_filter_event (GdkXEvent *xev,
           }
         else
           {
-            g_queue_push_tail (&priv->chunks, bytes);
-
             if (type == gdk_x11_get_xatom_by_name_for_display (priv->display, "INCR"))
               {
                 /* The remainder of the selection will come through PropertyNotify
                    events on xwindow */
                 GDK_NOTE(SELECTION, g_print ("%s:%s: initiating INCR transfer\n", priv->selection, priv->target));
+                priv->incr = TRUE;
                 gdk_x11_selection_input_stream_flush (stream);
               }
             else
               {
+                g_queue_push_tail (&priv->chunks, bytes);
+
                 gdk_x11_selection_input_stream_complete (stream);
               }